
#include "MainHeader.h"




int DecodeOAM() {
	
	u16 spritecount=0;
	u8 ttype=0;
	u16 i=0;
	u32 so=0; 
	//Dim bam As String
	u16 OAM0=0;
	u16 OAM1=0;
	u16 OAM2=0;
	for(spritecount = 0; spritecount<maxsprite; spritecount++) {
		ttype =sprite_in[spritecount].sprtype;
		if(ttype==0) 
			continue;
		if(!SpriteOAM[ttype]) 
			continue;
	
		fseek(GBA.ROM, SpriteOAM[ttype], SEEK_SET);
		fread(&so, 4, 1, GBA.ROM);
		fseek(GBA.ROM, so-0x8000000, SEEK_SET);
		fread(&SpriteNo[spritecount], 2, 1, GBA.ROM);
		
		if(SpriteNo[spritecount]>=128)SpriteNo[spritecount]=0;
		for( i=0; i< SpriteNo[spritecount]; i++) {
			fread(&thisoam[spritecount][i].enOAM.OAM0, 2, 1, GBA.ROM);
			fread(&thisoam[spritecount][i].enOAM.OAM1, 2, 1, GBA.ROM);
			fread(&thisoam[spritecount][i].enOAM.OAM2, 2, 1, GBA.ROM);
		}
	}
	
	for(spritecount = 0; spritecount< maxsprite; spritecount++) {
		
		for( i=0; i<  SpriteNo[spritecount]; i++) {
			OAM0=thisoam[spritecount][i].enOAM.OAM0;
			OAM1=thisoam[spritecount][i].enOAM.OAM1;
			OAM2=thisoam[spritecount][i].enOAM.OAM2;
			thisoam[spritecount][i].deOAM.yCoord = (OAM0 & 0xFF);
			
			thisoam[spritecount][i].deOAM.objRot = GetBitField(OAM0, 8, 1);
			thisoam[spritecount][i].deOAM.DSaOD = GetBitField(OAM0, 9, 1);
			thisoam[spritecount][i].deOAM.ObjMode = GetBitField(OAM0, 10, 2);
			thisoam[spritecount][i].deOAM.ObjMosiac = GetBitField(OAM0, 12, 1);
			thisoam[spritecount][i].deOAM.Paltype = GetBitField(OAM0, 13, 1);
			thisoam[spritecount][i].deOAM.ObjShape = GetBitField(OAM0, 14, 2);
			
			//OAM1
			thisoam[spritecount][i].deOAM.xCoord = GetBitField(OAM1, 0, 8);
			
			if (GetBitField(OAM0, 8, 1) == 1) {
				thisoam[spritecount][i].deOAM.rotation = GetBitField(OAM1, 9, 5);
			} else {
				thisoam[spritecount][i].deOAM.HorizontalFlip = (OAM1 & 0x400 ? 1:0);
				thisoam[spritecount][i].deOAM.VerticalFlip = (OAM1 & 0x800	? 1:0);
			}
			
			thisoam[spritecount][i].deOAM.ObjSize =OAM1>>14;
			thisoam[spritecount][i].deOAM.TileNumber = OAM2 & 0x3FF;
			thisoam[spritecount][i].deOAM.Palette = (OAM2 & 0xF000) / 0x1000;
		}
	}
	return 0;
}


int GetBitField( long reg , long bitStart, long bitLength) {
	return	(reg / (1<< bitStart)) & ((1<< bitLength) - 1);
}

int DrawOAM(u8 cursprite) {
	int width=0;
	int height=0;
	int i =0;
	int Tile=0;
	int bTile=0;
	int Pal=0;
	int fw=0;
	int fh=0;
	int ty=0;
	int tx=0;
	int sx=0;
	int sy=0;
	int xFlip=0;
	int yFlip=0;
	RECT PartSize[128]={0};
	const u8 objSizes[3][4][2]=
	{
		{ { 8, 8}, {16,16}, {32,32}, {64,64} }, 
		{ {16, 8}, {32, 8}, {32,16}, {64,32} },
		{ { 8,16}, { 8,32}, {16,32}, {32,64} },
	};
	
	Image OamBuffer; 
	SpriteImage.Load(VRAM.RAM, 1023);
	


	sx = 0;
	sy = 0;

	tx = 0;
	ty = 0;
    OamBuffer.Create(256, 256);
	OamBuffer.SetPalette(SprPal);

	OverAllOAM *obj;
  
	//Draw reverse order
for(i = SpriteNo[cursprite]-1;i>=0; i--){
	if(SpriteNo[cursprite]-i>=0x100){

		MessageBox(0,"There's a bad part in this sprite, exiting drawing.","Error",MB_OK);
		break;
	}
//	for(i = 0; i<SpriteNo[cursprite]; i++) {
		obj= &thisoam[cursprite][SpriteNo[cursprite]-i-1];

		if (obj->deOAM.ObjShape == 3)
			continue;

		sx = (obj->enOAM.OAM1 & 511);
		sy = (obj->enOAM.OAM0 & 255);
		if (sy & 0x80) 
			sy = sy - 256; //check for the negative
		if (sx &  0x100)  
			sx = sx - 511; //same here
         
		sx = sx + 128;
		sy = sy + 128;
		//Set up the basic tile
    
       
	
		int Pal =( ((thisoam[cursprite][SpriteNo[cursprite]-i-1].enOAM.OAM2&0xF000)>>0xC) + 
			(sprite_in[cursprite].sprdetail))* 4096;

		//MsgBox "Out of Memory Bounds": Exit Function
		Tile=Pal + (sprite_in[cursprite].sprdetail * 2048) / 32 + 
			(thisoam[cursprite][SpriteNo[cursprite]-i-1].enOAM.OAM2 & 0x3FF);
		//Tile+=obj->deOAM.VerticalFlip*0x800;

		//Now switch on this and find the sprite width and height.


		width = objSizes[obj->enOAM.OAM0>>14][obj->enOAM.OAM1>>14][0];
		height= objSizes[obj->enOAM.OAM0>>14][obj->enOAM.OAM1>>14][1];
        PartSize[SpriteNo[cursprite]-i-1].left =sx;
		PartSize[SpriteNo[cursprite]-i-1].top =sy;
        PartSize[SpriteNo[cursprite]-i-1].right =width;
		PartSize[SpriteNo[cursprite]-i-1].bottom =height;
		xFlip= yFlip= fh= fw= 0;

		if(obj->enOAM.OAM1 & 0x1000) {
			//formula goes here;
			xFlip= width/8-1; //if width = 16 y
			fw = 0x400;
		} 
		if(obj->enOAM.OAM1 & 0x2000 ) {
			yFlip = height/8-1;
			fh = 0x800;
		} 

		for(ty=0; ty<height/8; ty++) {

			for(tx=0; tx<width/8; tx++) {

				OamBuffer.Draw(SpriteImage, sx + (tx^xFlip)*8,
					sy + ((ty)^yFlip)*8, Tile+tx+(ty*32)+fh+fw);
				
			}
		}
		

/*     
		HDC hdc= OamBuffer.DC();
		HPEN pen;
		pen= CreatePen(PS_SOLID, 1, i==0 ? RGB(255,0,0) : RGB(0, 255, 255));

		HPEN oldPen= (HPEN)SelectObject(hdc, pen);
		HBRUSH oldBrush= (HBRUSH)SelectObject(hdc, GetStockObject(HOLLOW_BRUSH));
		Rectangle(hdc, sx, sy, sx+width, sy+width);
		SelectObject(hdc, oldBrush);		
		SelectObject(hdc, oldPen);*/
	}

	//Determine i
if(SpriteNo[cursprite]-1>127) return 0;
	OverallSize[cursprite].left =PartSize[SpriteNo[cursprite]-1].left;
	OverallSize[cursprite].top =PartSize[SpriteNo[cursprite]-1].top;
   	OverallSize[cursprite].right =PartSize[SpriteNo[cursprite]-1].left+PartSize[SpriteNo[cursprite]-1].right;
	OverallSize[cursprite].bottom =PartSize[SpriteNo[cursprite]-1].top+PartSize[SpriteNo[cursprite]-1].bottom;

	for(i = 1; i<SpriteNo[cursprite]; i++) {
		 //Check for top coord 
		 //0 = Starting X
		 //1 = Startiny Y
		 //2 = Width
		 //3 = Height
		if(PartSize[SpriteNo[cursprite]-i-1].left<OverallSize[cursprite].left) 
			OverallSize[cursprite].left = PartSize[SpriteNo[cursprite]-i-1].left;
		if(PartSize[SpriteNo[cursprite]-i-1].top<OverallSize[cursprite].top) 
			OverallSize[cursprite].top = PartSize[SpriteNo[cursprite]-i-1].top;

		OverallSize[cursprite].right= 
			max(OverallSize[cursprite].right, PartSize[SpriteNo[cursprite]-i-1].left+PartSize[SpriteNo[cursprite]-i-1].right);
		OverallSize[cursprite].bottom= 
			max(OverallSize[cursprite].bottom, PartSize[SpriteNo[cursprite]-i-1].top+PartSize[SpriteNo[cursprite]-i-1].bottom);

	}
	
	SpritePics[cursprite].Create(OverallSize[cursprite].right-OverallSize[cursprite].left,	
		OverallSize[cursprite].bottom-OverallSize[cursprite].top);

	SpritePics[cursprite].SetPalette(SprPal);
/*	BitBlt(SpritePics[cursprite].DC(), 0, 0, 
		OverallSize[cursprite].right-OverallSize[cursprite].left,
		OverallSize[cursprite].bottom-OverallSize[cursprite].top,
		OamBuffer.DC(), OverallSize[cursprite].left, OverallSize[cursprite].top, 
		SRCCOPY);*/
	OamBuffer.Blit(SpritePics[cursprite].DC(), 0, 0, 
		OverallSize[cursprite].right-OverallSize[cursprite].left,
		OverallSize[cursprite].bottom-OverallSize[cursprite].top,
		OverallSize[cursprite].left, OverallSize[cursprite].top);

	
	InvalidateRect(hwndMap, 0, 1);

	return 0;
}



